﻿/**
 * \file Joueur.cs
 * \brief Classe Joueur
 * \author ARTUR Vincent
 * \author LAPERDRIX Pierre
 * \version 1.0
 */
namespace Implem
{
	using Interfaces;
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;
    using System.IO;
    using System.Windows.Media;

    /**
     * \class Joueur
     * \brief Objet representant un joueur
     */
	public class Joueur : IJoueur
	{
        /**!< Constantes pour la sauvegarde */
        private const char INFO = 'i';
        private const char EII = 'e';

        /*!< Nom du joueur */
        private string _nom;

        /*!< Propriete accedant a l'attribut _nom*/
        public string Nom
        {
            get { return _nom; }
            set { _nom = value; }
        }

        /*!< Couleur du joueur */
        private Color _couleur;

        /*!< Propriete accedant a l'attribut _couleur*/
        public Color Couleur
        {
            get { return _couleur; }
            set { _couleur = value; }
        }

        /*!< Liste contenant les villes appartenant au joueur */
		private List<Ville> _villes;

        /*!< Propriete accedant a la liste _villes */
        public List<Ville> Villes
		{
            get { return _villes; }
            set { _villes = value; }
		}

        /*!< Liste contenant les etudiants appartenant au joueur */
		private List<IEtudiant> _etudiants;

        /*!< Propriete accedant a la liste _etudiants */
        public List<IEtudiant> Etudiants
		{
            get { return _etudiants; }
            set { _etudiants = value; }
		}

        /*!< Liste contenant les enseignants appartenant au joueur */
		private List<IEnseignant> _enseignants;

        /*!< Propriete accedant a la liste _enseignants */
        public List<IEnseignant> Enseignants
		{
            get { return _enseignants; }
            set { _enseignants = value; }
		}

        /*!< Directeur appartenant au joueur */
		private IDirecteur _directeur;

        /*!< Propriete accedant a l'attribut _directeur */
        public IDirecteur Directeur
		{
            get { return _directeur; }
            set { _directeur = value; }
		}

        /*!< Fabrique d'unites du joueur */
        private IFabriqueUnite fab{
            get;
            set;
        }

        /**
         * \fn public Joueur(typeCivil t,Position posDepart)
         * \brief Constructeur de joueur
         * \param t le type de civilisation
         * \param posDepart la position de depart du joueur
         */
        public Joueur(string n, Color c, typeCivil t, Position posDepart)
        {
            //Initialisation du nom du joueur
            Nom = n;

            //Initialisation de la couleur du joueur
            Couleur = c;

            //Initialisation de la fabrique du joueur
            switch (t)
            {
                case typeCivil.eii: this.fab = FabriqueUniteEII.INSTANCE; break;
                case typeCivil.info: this.fab = FabriqueUniteINFO.INSTANCE; break;
                default: break;
            }
           
            //Initialisation des deux premieres unites
            _directeur = null;

            _etudiants = new List<IEtudiant>();
            _etudiants.Add(fab.creerEtudiant(this, posDepart));
            Carte.ajoutUnite((Unite)_etudiants[0]);

            _enseignants = new List<IEnseignant>();
            _enseignants.Add(fab.creerEnseignant(this, posDepart));
            Carte.ajoutUnite((Unite)_enseignants[0]);

            _villes = new List<Ville>();

        }


        /**
         * \fn public void produireUnite(typeProduction t,Position posVille)
         * \brief Produit une unite dans une ville
         * \param t le type d'unite a produire
         * \param posVille la position de la ville
         */
        public IUnite produireUnite(typeProduction t, Position posVille)
        {
            switch (t)
            {
                case typeProduction.aucune:
                    return null;
                case typeProduction.directeur :
                    if (this._directeur == null)
                    {
                        IDirecteur d = (IDirecteur)fab.creerDirecteur(this,posVille);
                        this._directeur = d;
                        return d;
                    }
                    else
                    {
                        return null;
                    }

                case typeProduction.enseignant :
                    IEnseignant en = (IEnseignant)fab.creerEnseignant(this, posVille);
                    this._enseignants.Add(en);
                    return en;
                case typeProduction.etudiant :
                    IEtudiant et = (IEtudiant)fab.creerEtudiant(this, posVille);
                    this._etudiants.Add(et);
                    return et;
                default : return null;
            }
        }

        /**
         * \fn public void nouveauTour()
         * \brief Change le joueur courant de la partie
         */
        public void nouveauTour()
        {
            Partie.joueurCourant = this;
        }


        /**
         * \fn public void finTour()
         * \brief Execute les actions de fin de tour
         */
        public void finTour()
        {
            //Recuperation des ressoucres dans chaque ville et production d'unites si besoin
            foreach (Ville v in this._villes)
            {
                v.finTour();
            }

            //Gain de PV pour les unites non utilisees pendant le tour
            if (Directeur != null)
            {
                Directeur.gainPV();
                Directeur.refreshMouvement();
            }
            foreach(IEtudiant et in Etudiants){
                et.gainPV();
                et.refreshMouvement();
            }
            foreach (IEnseignant en in Enseignants)
            {
                en.gainPV();
                en.refreshMouvement();
            }

        }

        /**
         * \fn public Ville nouvelleVille(Position p,String s)
         * \brief Cree une nouvelle ville
         * \param p la position de la ville
         * \param s le nom de la ville
         * \return la nouvelle ville
         */
        public Ville nouvelleVille(Position p)
        {
            Ville res = new Ville(this, p);
            this._villes.Add(res);
            return res;
        }


        /**
         * \fn public void save(StreamWriter sw)
         * \brief Sauvegarde du joueur
         * \param sw le flux dans lequel ecrire
         */
        public void save(StreamWriter sw)
        {
            sw.WriteLine(Nom);
            sw.WriteLine(Villes.Count);
            foreach (Ville v in Villes)
            {
                v.save(sw);
            }
            
            if (fab is FabriqueUniteEII) sw.WriteLine(EII);
            else if (fab is FabriqueUniteINFO) sw.WriteLine(INFO);
            sw.WriteLine((Directeur != null) ? '1' : '0');
            if(Directeur != null) ((Unite)Directeur).save(sw);
            sw.WriteLine(Etudiants.Count);
            foreach (Unite u in Etudiants)
            {
                u.save(sw);
            }
            sw.WriteLine(Enseignants.Count);
            foreach (Unite u in Enseignants)
            {
                u.save(sw);
            }
            sw.WriteLine((char)this.Couleur.R);
            sw.WriteLine((char)this.Couleur.G);
            sw.WriteLine((char)this.Couleur.B);
            
        }

        /**
         * \fn public void load(StreamReader sr)
         * \brief Chargement d'un joueur
         * \param sr le flux dans lequel lire
         */
        public void load(StreamReader sr)
        {
            Nom = sr.ReadLine();
            int nbvilles = Convert.ToInt32(sr.ReadLine());
            this.Villes.Clear();
            for (int i = 0; i < nbvilles; i++)
            {
                Ville v = new Ville(this,new Position(0,0));
                v.load(sr,this);
                Villes.Add(v);

                for (int k = 0; k < 5; k++)
                {
                    for (int l = 0; l < 5; l++)
                    {
                        if (v.Expansion[k][l] || v.VilleExt[k][l] == 1)
                        {
                            Carte.Villes[new Position(v.PositCentrale.X + k - 2, v.PositCentrale.Y + l - 2)] = v;
                        }
                    }
                }
            }
            
            char c = (char)sr.Read();
            if (c == INFO) fab = FabriqueUniteINFO.INSTANCE;
            else fab = FabriqueUniteEII.INSTANCE;
            sr.ReadLine();

            char d = (char)sr.Read();
            if (d == '1')
            {
                Unite dir = (Unite)fab.creerDirecteur(this, new Position(0, 0));
                dir.load(sr, this);
                Directeur = (IDirecteur)dir;
            }
            sr.ReadLine();

            List<IEtudiant> letud = new List<IEtudiant>();
            int nbetud = Convert.ToInt32(sr.ReadLine());
            for (int i = 0; i < nbetud; i++)
            {
                Unite etu = (Unite)fab.creerEtudiant(this,(new Position(0,0)));
                etu.load(sr,this);
                letud.Add((IEtudiant)etu);
            }
            this.Etudiants = letud;

            List<IEnseignant> lens = new List<IEnseignant>();
            int nbens = Convert.ToInt32(sr.ReadLine());
            for (int i = 0; i < nbens; i++)
            {
                Unite ens = (Unite)fab.creerEnseignant(this,(new Position(0,0)));
                ens.load(sr,this);
                lens.Add((IEnseignant)ens);
            }
            this.Enseignants = lens;
            byte r = (byte)sr.Read();
            sr.ReadLine();
            byte g = (byte)sr.Read();
            sr.ReadLine();
            byte b = (byte)sr.Read();
            sr.ReadLine();
            this.Couleur = Color.FromRgb(r, g, b);



        }


	}
}

